package br.zeos;

import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

public class ZDataSource {

    private br.zeos.ZSql sql = null;
    private HashMap<String, String> linha = new HashMap<String, String>();
    private ArrayList<HashMap<String, String>> dados = new ArrayList<HashMap<String, String>>();
    private int index = 0;
    private ArrayList<ActionListener> updateListener = new ArrayList<ActionListener>();

    public void Filter(String value) {
        this.Reload();
        for (int i = 0; i < dados.size(); i++) {
            HashMap<String, String> dado = dados.get(i);
            boolean vai = false;
            for (Map.Entry<String, String> l : dado.entrySet()) {
                String campo = l.getKey().toUpperCase();
                String valor = l.getValue().toUpperCase();
                vai = valor.contains(value.toUpperCase()) && !valor.isEmpty();
                if ( vai )
                    break;
            }
            
            if (!vai) {
                this.dados.remove(i);
                i--;
            }
        }
        for (ActionListener al : this.updateListener) {
            al.actionPerformed(null);
        }
    }

    public void Reload() {
        this.dados = this.sql.Select();
    }
   
    public void Where(String where) {
        this.dados = this.sql.Select(where);
    }

    public br.zeos.ZSql getSql() {
        return sql;
    }

    public void setSql(br.zeos.ZSql sql) {
        this.sql = sql;
    }

    public HashMap<String, String> getLine() {
        return linha;
    }

    public void setLinha(HashMap<String, String> linha) {
        this.linha = linha;
    }

    public ArrayList<HashMap<String, String>> getData() {
        return dados;
    }

    public void setData(ArrayList<HashMap<String, String>> dados) {
        this.dados = dados;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    public void addUpdateListener(ActionListener updateListener) {        
        this.updateListener.add(updateListener);
    }

    public ZDataSource(br.zeos.ZSql sql) {
        this.sql = sql;
        this.Reload();
    }

    public ZDataSource(ZConnect conexao, String tableName) {
        this.sql = new ZSql(new ZTable(conexao, tableName));
        this.Reload();
    }

    public void moveFirst() {
        if (this.dados.size() < 1) {
            return;
        }
        this.index = 0;
        linha = this.dados.get(this.index);
        for (ActionListener al : this.updateListener) {
            al.actionPerformed(null);
        }
    }

    public void moveLast() {
        if (this.dados.size() < 1) {
            return;
        }
        this.index = this.dados.size() - 1;
        linha = this.dados.get(this.index);
        for (ActionListener al : this.updateListener) {
            al.actionPerformed(null);
        }
    }

    public void moveNext() {
        if (this.dados.size() < 1) {
            return;
        }
        if (this.index >= this.dados.size() - 1) {
            this.index = this.dados.size() - 1;
        } else {
            this.index++;
        }
        linha = this.dados.get(this.index);
        for (ActionListener al : this.updateListener) {
            al.actionPerformed(null);
        }
    }

    public void movePrevious() {
        if (this.dados.size() < 1) {
            return;
        }
        if (this.index < 1) {
            this.index = 0;
        } else {
            this.index--;
        }
        linha = this.dados.get(this.index);
        for (ActionListener al : this.updateListener) {
            al.actionPerformed(null);
        }
    }

    public void moveTo(int index) {
        if (this.dados.size() < 1) {
            return;
        }
        this.index = index;
        if (this.index < 1) {
            this.index = 0;
        } else {
            this.index--;
        }
        if (this.index > this.dados.size() - 1) {
            this.index = this.dados.size() - 1;
        } else {
            this.index++;
        }
        linha = this.dados.get(this.index);
        for (ActionListener al : this.updateListener) {
            al.actionPerformed(null);
        }
    }

    public void Insert() {
        for (Map.Entry<String, String> l : linha.entrySet()) {
            String campo = l.getKey();
            String valor = l.getValue();
            this.sql.putField(campo.toUpperCase(), valor);
        }
        this.sql.Insert();
        this.Reload();
        for (ActionListener al : this.updateListener) {
            al.actionPerformed(null);
        }
    }

    public void Update() {
        if (this.dados.size() < 1) {
            return;
        }
        for (Map.Entry<String, String> l : linha.entrySet()) {
            String campo = l.getKey();
            String valor = l.getValue();
            if (valor == null) {
                continue;
            }
            this.sql.putField(campo.toUpperCase(), valor);
        }
        String nomePK = this.sql.getTabela().getPrimaryKeyName().toUpperCase();
        this.sql.putParameter(":ID", this.linha.get(nomePK), ZSql.Tipos.Integer);
        this.sql.Update(this.sql.getTabela().getPrimaryKeyName() + "= :ID");
//        this.sql.Update(nomePK + "= '" + valorPK + "'");
        this.Reload();
        for (ActionListener al : this.updateListener) {
            al.actionPerformed(null);
        }
    }

    public void Delete() {
        if (this.dados.size() < 1) {
            return;
        }
        this.sql.putParameter(":id", this.linha.get(this.sql.getTabela().getPrimaryKeyName()), ZSql.Tipos.Integer);
        this.sql.Delete(this.sql.getTabela().getPrimaryKeyName() + "= :ID");
        this.Reload();
        for (ActionListener al : this.updateListener) {
            al.actionPerformed(null);
        }
    }

    /**
     * Em caso de necessidade de extender
     *
     * @param field campo que será resgatado
     * @param data valor do campo
     * @return valor a ser retornado normalmente retorna o data
     */
    public String get(String field, String data) {
        return data;
    }

}
